use super::super::ggg::*;
use super::*;

#[derive(Debug, Clone)]
pub struct Table<'a> {
	// uint16	majorVersion	Major version of the MATH table, = 1.
	pub major_version: u16,
	// uint16	minorVersion	Minor version of the MATH table, = 0.
	pub minor_version: u16,
	// Offset16	mathConstantsOffset	Offset to MathConstants table, from the beginning of MATH table.
	pub math_constants: Option<MathConstants<'a>>,
	// Offset16	mathGlyphInfoOffset	Offset to MathGlyphInfo table, from the beginning of MATH table.
	pub math_glyph_info: Option<MathGlyphInfo<'a>>,
	// Offset16	mathVariantsOffset	Offset to MathVariants table, from the beginning of MATH table.
	pub math_variants: Option<MathVariants<'a>>,
}
impl<'a> FromSlice<'a> for Table<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			major_version: s.read()?,
			minor_version: s.read()?,
			math_constants: s.parse_at_offset16(data),
			math_glyph_info: s.parse_at_offset16(data),
			math_variants: s.parse_at_offset16(data),
		})
	}
}

#[derive(Debug, Clone, Copy)]
pub struct MathValueRecord {
	// FWORD	value	The X or Y value in design units.
	pub value: FWORD,
	// Offset16	deviceOffset	Offset to the device table, from the beginning of parent table. May be NULL. Suggested format for device table is 1.
	pub device: Option<Offset16>,
}
impl FromData for MathValueRecord {
	const SIZE: usize = 4;
	fn parse(data: &[u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			value: s.read()?,
			device: s.read()?,
		})
	}
}
#[derive(Debug, Clone, Copy)]
pub struct MathValue<'a> {
	pub value: FWORD,
	pub device: Option<Device<'a>>,
}
impl<'a> MathValue<'a> {
	pub fn new(r: MathValueRecord, base: &'a [u8]) -> Self {
		Self {
			value: r.value,
			device: r.device.and_then(|v| base.get(v.to_usize()..)).and_then(Device::parse),
		}
	}
}

#[derive(Debug, Clone)]
pub struct MathConstants<'a> {
	// int16	scriptPercentScaleDown	Percentage of scaling down for level 1 superscripts and subscripts. Suggested value: 80%.
	pub script_percent_scale_down: i16,
	// int16	scriptScriptPercentScaleDown	Percentage of scaling down for level 2 (scriptScript) superscripts and subscripts. Suggested value: 60%.
	pub script_script_percent_scale_down: i16,
	// UFWORD	delimitedSubFormulaMinHeight	Minimum height required for a delimited expression (contained within parentheses, etc.) to be treated as a sub-formula. Suggested value: normal line height × 1.5.
	pub delimited_sub_formula_min_height: UFWORD,
	// UFWORD	displayOperatorMinHeight	Minimum height of n-ary operators (such as integral and summation) for formulas in display mode (that is, appearing as standalone page elements, not embedded inline within text).
	pub display_operator_min_height: UFWORD,
	// MathValueRecord	mathLeading	White space to be left between math formulas to ensure proper line spacing. For example, for applications that treat line gap as a part of line ascender, formulas with ink going above (os2.sTypoAscender + os2.sTypoLineGap - MathLeading) or with ink going below os2.sTypoDescender will result in increasing line height.
	pub math_leading: MathValue<'a>,
	// MathValueRecord	axisHeight	Axis height of the font. In math typesetting, the term axis refers to a horizontal reference line used for positioning elements in a formula. The math axis is similar to but distinct from the baseline for regular text layout. For example, in a simple equation, a minus symbol or fraction rule would be on the axis, but a string for a variable name would be set on a baseline that is offset from the axis. The axisHeight value determines the amount of that offset.
	pub axis_height: MathValue<'a>,
	// MathValueRecord	accentBaseHeight	Maximum (ink) height of accent base that does not require raising the accents. Suggested: x‑height of the font (os2.sxHeight) plus any possible overshots.
	pub accent_base_height: MathValue<'a>,
	// MathValueRecord	flattenedAccentBaseHeight	Maximum (ink) height of accent base that does not require flattening the accents. Suggested: cap height of the font (os2.sCapHeight).
	pub flattened_accent_base_height: MathValue<'a>,
	// MathValueRecord	subscriptShiftDown	The standard shift down applied to subscript elements. Positive for moving in the downward direction. Suggested: os2.ySubscriptYOffset.
	pub subscript_shift_down: MathValue<'a>,
	// MathValueRecord	subscriptTopMax	Maximum allowed height of the (ink) top of subscripts that does not require moving subscripts further down. Suggested: 4/5 x- height.
	pub subscript_top_max: MathValue<'a>,
	// MathValueRecord	subscriptBaselineDropMin	Minimum allowed drop of the baseline of subscripts relative to the (ink) bottom of the base. Checked for bases that are treated as a box or extended shape. Positive for subscript baseline dropped below the base bottom.
	pub subscript_baseline_drop_min: MathValue<'a>,
	// MathValueRecord	superscriptShiftUp	Standard shift up applied to superscript elements. Suggested: os2.ySuperscriptYOffset.
	pub superscript_shift_up: MathValue<'a>,
	// MathValueRecord	superscriptShiftUpCramped	Standard shift of superscripts relative to the base, in cramped style.
	pub superscript_shift_up_cramped: MathValue<'a>,
	// MathValueRecord	superscriptBottomMin	Minimum allowed height of the (ink) bottom of superscripts that does not require moving subscripts further up. Suggested: ¼ x-height.
	pub superscript_bottom_min: MathValue<'a>,
	// MathValueRecord	superscriptBaselineDropMax	Maximum allowed drop of the baseline of superscripts relative to the (ink) top of the base. Checked for bases that are treated as a box or extended shape. Positive for superscript baseline below the base top.
	pub superscript_baseline_drop_max: MathValue<'a>,
	// MathValueRecord	subSuperscriptGapMin	Minimum gap between the superscript and subscript ink. Suggested: 4 × default rule thickness.
	pub sub_superscript_gap_min: MathValue<'a>,
	// MathValueRecord	superscriptBottomMaxWithSubscript	The maximum level to which the (ink) bottom of superscript can be pushed to increase the gap between superscript and subscript, before subscript starts being moved down. Suggested: 4/5 x-height.
	pub superscript_bottom_max_with_subscript: MathValue<'a>,
	// MathValueRecord	spaceAfterScript	Extra white space to be added after each subscript and superscript that occurs after a baseline element, and before each subscript and superscript that occurs before a baseline element. Suggested: 0.5 pt for a 12 pt font. Note that, in some math layout implementations, a constant value, such as 0.5 pt, could be used for all text sizes. Some implementations could use a constant ratio of text size, such as 1/24 of em.
	pub space_after_script: MathValue<'a>,
	// MathValueRecord	upperLimitGapMin	Minimum gap between the (ink) bottom of the upper limit, and the (ink) top of the base operator.
	pub upper_limit_gap_min: MathValue<'a>,
	// MathValueRecord	upperLimitBaselineRiseMin	Minimum distance between baseline of upper limit and (ink) top of the base operator.
	pub upper_limit_baseline_rise_min: MathValue<'a>,
	// MathValueRecord	lowerLimitGapMin	Minimum gap between (ink) top of the lower limit, and (ink) bottom of the base operator.
	pub lower_limit_gap_min: MathValue<'a>,
	// MathValueRecord	lowerLimitBaselineDropMin	Minimum distance between baseline of the lower limit and (ink) bottom of the base operator.
	pub lower_limit_baseline_drop_min: MathValue<'a>,
	// MathValueRecord	stackTopShiftUp	Standard shift up applied to the top element of a stack.
	pub stack_top_shift_up: MathValue<'a>,
	// MathValueRecord	stackTopDisplayStyleShiftUp	Standard shift up applied to the top element of a stack in display style.
	pub stack_top_display_style_shift_up: MathValue<'a>,
	// MathValueRecord	stackBottomShiftDown	Standard shift down applied to the bottom element of a stack. Positive for moving in the downward direction.
	pub stack_bottom_shift_down: MathValue<'a>,
	// MathValueRecord	stackBottomDisplayStyleShiftDown	Standard shift down applied to the bottom element of a stack in display style. Positive for moving in the downward direction.
	pub stack_bottom_display_style_shift_down: MathValue<'a>,
	// MathValueRecord	stackGapMin	Minimum gap between (ink) bottom of the top element of a stack, and the (ink) top of the bottom element. Suggested: 3 × default rule thickness.
	pub stack_gap_min: MathValue<'a>,
	// MathValueRecord	stackDisplayStyleGapMin	Minimum gap between (ink) bottom of the top element of a stack, and the (ink) top of the bottom element in display style. Suggested: 7 × default rule thickness.
	pub stack_display_style_gap_min: MathValue<'a>,
	// MathValueRecord	stretchStackTopShiftUp	Standard shift up applied to the top element of the stretch stack.
	pub stretch_stack_top_shift_up: MathValue<'a>,
	// MathValueRecord	stretchStackBottomShiftDown	Standard shift down applied to the bottom element of the stretch stack. Positive for moving in the downward direction.
	pub stretch_stack_bottom_shift_down: MathValue<'a>,
	// MathValueRecord	stretchStackGapAboveMin	Minimum gap between the ink of the stretched element, and the (ink) bottom of the element above. Suggested: same value as upperLimitGapMin.
	pub stretch_stack_gap_above_min: MathValue<'a>,
	// MathValueRecord	stretchStackGapBelowMin	Minimum gap between the ink of the stretched element, and the (ink) top of the element below. Suggested: same value as lowerLimitGapMin.
	pub stretch_stack_gap_below_min: MathValue<'a>,
	// MathValueRecord	fractionNumeratorShiftUp	Standard shift up applied to the numerator.
	pub fraction_numerator_shift_up: MathValue<'a>,
	// MathValueRecord	fractionNumeratorDisplayStyleShiftUp	Standard shift up applied to the numerator in display style. Suggested: same value as stackTopDisplayStyleShiftUp.
	pub fraction_numerator_display_style_shift_up: MathValue<'a>,
	// MathValueRecord	fractionDenominatorShiftDown	Standard shift down applied to the denominator. Positive for moving in the downward direction.
	pub fraction_denominator_shift_down: MathValue<'a>,
	// MathValueRecord	fractionDenominatorDisplayStyleShiftDown	Standard shift down applied to the denominator in display style. Positive for moving in the downward direction. Suggested: same value as stackBottomDisplayStyleShiftDown.
	pub fraction_denominator_display_style_shift_down: MathValue<'a>,
	// MathValueRecord	fractionNumeratorGapMin	Minimum tolerated gap between the (ink) bottom of the numerator and the ink of the fraction bar. Suggested: default rule thickness.
	pub fraction_numerator_gap_min: MathValue<'a>,
	// MathValueRecord	fractionNumDisplayStyleGapMin	Minimum tolerated gap between the (ink) bottom of the numerator and the ink of the fraction bar in display style. Suggested: 3 × default rule thickness.
	pub fraction_num_display_style_gap_min: MathValue<'a>,
	// MathValueRecord	fractionRuleThickness	Thickness of the fraction bar. Suggested: default rule thickness.
	pub fraction_rule_thickness: MathValue<'a>,
	// MathValueRecord	fractionDenominatorGapMin	Minimum tolerated gap between the (ink) top of the denominator and the ink of the fraction bar. Suggested: default rule thickness.
	pub fraction_denominator_gap_min: MathValue<'a>,
	// MathValueRecord	fractionDenomDisplayStyleGapMin	Minimum tolerated gap between the (ink) top of the denominator and the ink of the fraction bar in display style. Suggested: 3 × default rule thickness.
	pub fraction_denom_display_style_gap_min: MathValue<'a>,
	// MathValueRecord	skewedFractionHorizontalGap	Horizontal distance between the top and bottom elements of a skewed fraction.
	pub skewed_fraction_horizontal_gap: MathValue<'a>,
	// MathValueRecord	skewedFractionVerticalGap	Vertical distance between the ink of the top and bottom elements of a skewed fraction.
	pub skewed_fraction_vertical_gap: MathValue<'a>,
	// MathValueRecord	overbarVerticalGap	Distance between the overbar and the (ink) top of the base. Suggested: 3 × default rule thickness.
	pub overbar_vertical_gap: MathValue<'a>,
	// MathValueRecord	overbarRuleThickness	Thickness of overbar. Suggested: default rule thickness.
	pub overbar_rule_thickness: MathValue<'a>,
	// MathValueRecord	overbarExtraAscender	Extra white space reserved above the overbar. Suggested: default rule thickness.
	pub overbar_extra_ascender: MathValue<'a>,
	// MathValueRecord	underbarVerticalGap	Distance between underbar and (ink) bottom of the base. Suggested: 3 × default rule thickness.
	pub underbar_vertical_gap: MathValue<'a>,
	// MathValueRecord	underbarRuleThickness	Thickness of underbar. Suggested: default rule thickness.
	pub underbar_rule_thickness: MathValue<'a>,
	// MathValueRecord	underbarExtraDescender	Extra white space reserved below the underbar. Always positive. Suggested: default rule thickness.
	pub underbar_extra_descender: MathValue<'a>,
	// MathValueRecord	radicalVerticalGap	Space between the (ink) top of the expression and the bar over it. Suggested: 1¼ default rule thickness.
	pub radical_vertical_gap: MathValue<'a>,
	// MathValueRecord	radicalDisplayStyleVerticalGap	Space between the (ink) top of the expression and the bar over it. Suggested: default rule thickness + ¼ x-height.
	pub radical_display_style_vertical_gap: MathValue<'a>,
	// MathValueRecord	radicalRuleThickness	Thickness of the radical rule. This is the thickness of the rule in designed or constructed radical signs. Suggested: default rule thickness.
	pub radical_rule_thickness: MathValue<'a>,
	// MathValueRecord	radicalExtraAscender	Extra white space reserved above the radical. Suggested: same value as radicalRuleThickness.
	pub radical_extra_ascender: MathValue<'a>,
	// MathValueRecord	radicalKernBeforeDegree	Extra horizontal kern before the degree of a radical, if such is present. Suggested: 5/18 of em.
	pub radical_kern_before_degree: MathValue<'a>,
	// MathValueRecord	radicalKernAfterDegree	Negative kern after the degree of a radical, if such is present. Suggested: −10/18 of em.
	pub radical_kern_after_degree: MathValue<'a>,
	// int16	radicalDegreeBottomRaisePercent	Height of the bottom of the radical degree, if such is present, in proportion to the height (ascender + descender) of the radical sign. Suggested: 60%.
	pub radical_degree_bottom_raise_percent: i16,
}
impl<'a> FromSlice<'a> for MathConstants<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			script_percent_scale_down: s.read()?,
			script_script_percent_scale_down: s.read()?,
			delimited_sub_formula_min_height: s.read()?,
			display_operator_min_height: s.read()?,
			math_leading: MathValue::new(s.read()?, data),
			axis_height: MathValue::new(s.read()?, data),
			accent_base_height: MathValue::new(s.read()?, data),
			flattened_accent_base_height: MathValue::new(s.read()?, data),
			subscript_shift_down: MathValue::new(s.read()?, data),
			subscript_top_max: MathValue::new(s.read()?, data),
			subscript_baseline_drop_min: MathValue::new(s.read()?, data),
			superscript_shift_up: MathValue::new(s.read()?, data),
			superscript_shift_up_cramped: MathValue::new(s.read()?, data),
			superscript_bottom_min: MathValue::new(s.read()?, data),
			superscript_baseline_drop_max: MathValue::new(s.read()?, data),
			sub_superscript_gap_min: MathValue::new(s.read()?, data),
			superscript_bottom_max_with_subscript: MathValue::new(s.read()?, data),
			space_after_script: MathValue::new(s.read()?, data),
			upper_limit_gap_min: MathValue::new(s.read()?, data),
			upper_limit_baseline_rise_min: MathValue::new(s.read()?, data),
			lower_limit_gap_min: MathValue::new(s.read()?, data),
			lower_limit_baseline_drop_min: MathValue::new(s.read()?, data),
			stack_top_shift_up: MathValue::new(s.read()?, data),
			stack_top_display_style_shift_up: MathValue::new(s.read()?, data),
			stack_bottom_shift_down: MathValue::new(s.read()?, data),
			stack_bottom_display_style_shift_down: MathValue::new(s.read()?, data),
			stack_gap_min: MathValue::new(s.read()?, data),
			stack_display_style_gap_min: MathValue::new(s.read()?, data),
			stretch_stack_top_shift_up: MathValue::new(s.read()?, data),
			stretch_stack_bottom_shift_down: MathValue::new(s.read()?, data),
			stretch_stack_gap_above_min: MathValue::new(s.read()?, data),
			stretch_stack_gap_below_min: MathValue::new(s.read()?, data),
			fraction_numerator_shift_up: MathValue::new(s.read()?, data),
			fraction_numerator_display_style_shift_up: MathValue::new(s.read()?, data),
			fraction_denominator_shift_down: MathValue::new(s.read()?, data),
			fraction_denominator_display_style_shift_down: MathValue::new(s.read()?, data),
			fraction_numerator_gap_min: MathValue::new(s.read()?, data),
			fraction_num_display_style_gap_min: MathValue::new(s.read()?, data),
			fraction_rule_thickness: MathValue::new(s.read()?, data),
			fraction_denominator_gap_min: MathValue::new(s.read()?, data),
			fraction_denom_display_style_gap_min: MathValue::new(s.read()?, data),
			skewed_fraction_horizontal_gap: MathValue::new(s.read()?, data),
			skewed_fraction_vertical_gap: MathValue::new(s.read()?, data),
			overbar_vertical_gap: MathValue::new(s.read()?, data),
			overbar_rule_thickness: MathValue::new(s.read()?, data),
			overbar_extra_ascender: MathValue::new(s.read()?, data),
			underbar_vertical_gap: MathValue::new(s.read()?, data),
			underbar_rule_thickness: MathValue::new(s.read()?, data),
			underbar_extra_descender: MathValue::new(s.read()?, data),
			radical_vertical_gap: MathValue::new(s.read()?, data),
			radical_display_style_vertical_gap: MathValue::new(s.read()?, data),
			radical_rule_thickness: MathValue::new(s.read()?, data),
			radical_extra_ascender: MathValue::new(s.read()?, data),
			radical_kern_before_degree: MathValue::new(s.read()?, data),
			radical_kern_after_degree: MathValue::new(s.read()?, data),
			radical_degree_bottom_raise_percent: s.read()?,
		})
	}
}

#[derive(Debug, Clone)]
pub struct MathGlyphInfo<'a> {
	// Offset16	mathItalicsCorrectionInfoOffset	Offset to MathItalicsCorrectionInfo table, from the beginning of the MathGlyphInfo table.
	pub math_italics_correction_info: Option<MathItalicsCorrectionInfo<'a>>,
	// Offset16	mathTopAccentAttachmentOffset	Offset to MathTopAccentAttachment table, from the beginning of the MathGlyphInfo table.
	pub math_top_accent_attachment: Option<MathTopAccentAttachment<'a>>,
	// Offset16	extendedShapeCoverageOffset	Offset to ExtendedShapes coverage table, from the beginning of the MathGlyphInfo table. When the glyph to the left or right of a box is an extended shape variant, the (ink) box should be used for vertical positioning purposes, not the default position defined by values in MathConstants table. May be NULL.
	pub extended_shape_coverage: Option<Coverage<'a>>,
	// Offset16	mathKernInfoOffset	Offset to MathKernInfo table, from the beginning of the MathGlyphInfo table.
	pub math_kern_info: Option<MathKernInfo<'a>>,
}
impl<'a> FromSlice<'a> for MathGlyphInfo<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			math_italics_correction_info: s.parse_at_offset16(data),
			math_top_accent_attachment: s.parse_at_offset16(data),
			extended_shape_coverage: s.parse_at_offset16(data),
			math_kern_info: s.parse_at_offset16(data),
		})
	}
}

#[derive(Debug, Clone)]
pub struct MathItalicsCorrectionInfo<'a> {
	// Offset16	italicsCorrectionCoverageOffset	Offset to Coverage table, from the beginning of MathItalicsCorrectionInfo table.
	pub italics_correction_coverage: Coverage<'a>,
	// uint16	italicsCorrectionCount	Number of italics correction values. Should coincide with the number of covered glyphs.
	// MathValueRecord	italicsCorrection[italicsCorrectionCount]	Array of MathValueRecords defining italics correction values for each covered glyph.
	pub italics_correction: LazyArray16<'a, MathValueRecord>,
	pub data: &'a [u8],
}
impl<'a> FromSlice<'a> for MathItalicsCorrectionInfo<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			italics_correction_coverage: s.parse_at_offset16(data)?,
			italics_correction: s.parse_array16()?,
			data,
		})
	}
}
impl<'a> MathItalicsCorrectionInfo<'a> {
	pub fn get(&self, index: u16) -> Option<MathValue<'a>> {
		self.get_(self.italics_correction.get(index)?)
	}
	pub fn get_(&self, r: MathValueRecord) -> Option<MathValue<'a>> {
		Some(MathValue::new(r, self.data))
	}
}

#[derive(Debug, Clone)]
pub struct MathTopAccentAttachment<'a> {
	// Offset16	topAccentCoverageOffset	Offset to Coverage table, from the beginning of the MathTopAccentAttachment table.
	pub top_accent_coverage: Coverage<'a>,
	// uint16	topAccentAttachmentCount	Number of top accent attachment point values. Must be the same as the number of glyph IDs referenced in the Coverage table.
	// MathValueRecord	topAccentAttachment[topAccentAttachmentCount]	Array of MathValueRecords defining top accent attachment points for each covered glyph.
	pub top_accent_attachment: LazyArray16<'a, MathValueRecord>,
	pub data: &'a [u8],
}
impl<'a> FromSlice<'a> for MathTopAccentAttachment<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			top_accent_coverage: s.parse_at_offset16(data)?,
			top_accent_attachment: s.parse_array16()?,
			data,
		})
	}
}
impl<'a> MathTopAccentAttachment<'a> {
	pub fn get(&self, index: u16) -> Option<MathValue<'a>> {
		self.get_(self.top_accent_attachment.get(index)?)
	}
	pub fn get_(&self, r: MathValueRecord) -> Option<MathValue<'a>> {
		Some(MathValue::new(r, self.data))
	}
}

#[derive(Debug, Clone)]
pub struct MathKernInfo<'a> {
	// Offset16	mathKernCoverageOffset	Offset to Coverage table, from the beginning of the MathKernInfo table.
	pub math_kern_coverage: Coverage<'a>,
	// uint16	mathKernCount	Number of MathKernInfoRecords. Must be the same as the number of glyph IDs referenced in the Coverage table.
	// MathKernInfoRecord	mathKernInfoRecords[mathKernCount]	Array of MathKernInfoRecords, one for each covered glyph.
	pub math_kern_info_records: LazyArray16<'a, MathKernInfoRecord>,
	pub data: &'a [u8],
}
impl<'a> FromSlice<'a> for MathKernInfo<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			math_kern_coverage: s.parse_at_offset16(data)?,
			math_kern_info_records: s.parse_array16()?,
			data,
		})
	}
}
impl<'a> MathKernInfo<'a> {
	pub fn get(&self, index: u16) -> Option<MathKernInfoValue<'a>> {
		self.get_(self.math_kern_info_records.get(index)?)
	}
	pub fn get_(&self, r: MathKernInfoRecord) -> Option<MathKernInfoValue<'a>> {
		Some(MathKernInfoValue::new(r, self.data))
	}
}

#[derive(Debug, Clone, Copy)]
pub struct MathKernInfoRecord {
	// Offset16	topRightMathKernOffset	Offset to MathKern table for top right corner, from the beginning of the MathKernInfo table. May be NULL.
	pub top_right_math_kern: Option<Offset16>,
	// Offset16	topLeftMathKernOffset	Offset to MathKern table for the top left corner, from the beginning of the MathKernInfo table. May be NULL.
	pub top_left_math_kern: Option<Offset16>,
	// Offset16	bottomRightMathKernOffset	Offset to MathKern table for bottom right corner, from the beginning of the MathKernInfo table. May be NULL.
	pub bottom_right_math_kern: Option<Offset16>,
	// Offset16	bottomLeftMathKernOffset	Offset to MathKern table for bottom left corner, from the beginning of the MathKernInfo table. May be NULL.
	pub bottom_left_math_kern: Option<Offset16>,
}
impl FromData for MathKernInfoRecord {
	const SIZE: usize = 8;
	fn parse(data: &[u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			top_right_math_kern: s.read()?,
			top_left_math_kern: s.read()?,
			bottom_right_math_kern: s.read()?,
			bottom_left_math_kern: s.read()?,
		})
	}
}

#[derive(Debug, Clone)]
pub struct MathKernInfoValue<'a> {
	// Offset16	topRightMathKernOffset	Offset to MathKern table for top right corner, from the beginning of the MathKernInfo table. May be NULL.
	pub top_right_math_kern: Option<MathKern<'a>>,
	// Offset16	topLeftMathKernOffset	Offset to MathKern table for the top left corner, from the beginning of the MathKernInfo table. May be NULL.
	pub top_left_math_kern: Option<MathKern<'a>>,
	// Offset16	bottomRightMathKernOffset	Offset to MathKern table for bottom right corner, from the beginning of the MathKernInfo table. May be NULL.
	pub bottom_right_math_kern: Option<MathKern<'a>>,
	// Offset16	bottomLeftMathKernOffset	Offset to MathKern table for bottom left corner, from the beginning of the MathKernInfo table. May be NULL.
	pub bottom_left_math_kern: Option<MathKern<'a>>,
}
impl<'a> MathKernInfoValue<'a> {
	pub fn new(r: MathKernInfoRecord, base: &'a [u8]) -> Self {
		Self {
			top_right_math_kern: r
				.top_right_math_kern
				.and_then(|v| base.get(v.to_usize()..))
				.and_then(MathKern::parse),
			top_left_math_kern: r
				.top_left_math_kern
				.and_then(|v| base.get(v.to_usize()..))
				.and_then(MathKern::parse),
			bottom_right_math_kern: r
				.bottom_right_math_kern
				.and_then(|v| base.get(v.to_usize()..))
				.and_then(MathKern::parse),
			bottom_left_math_kern: r
				.bottom_left_math_kern
				.and_then(|v| base.get(v.to_usize()..))
				.and_then(MathKern::parse),
		}
	}
}

#[derive(Debug, Clone)]
pub struct MathKern<'a> {
	// uint16	heightCount	Number of heights at which the kern value changes.
	// MathValueRecord	correctionHeight[heightCount]	Array of correction heights, in design units, sorted from lowest to highest.
	pub correction_height: LazyArray16<'a, MathValueRecord>,
	// MathValueRecord	kernValues[heightCount + 1]	Array of kerning values for different height ranges. Negative values are used to move glyphs closer to each other.
	pub kern_values: LazyArray16<'a, MathValueRecord>,
	pub data: &'a [u8],
}
impl<'a> FromSlice<'a> for MathKern<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		let count: u16 = s.read()?;
		Some(Self {
			correction_height: s.read_array16(count)?,
			kern_values: s.read_array16(count)?,
			data,
		})
	}
}
impl<'a> MathKern<'a> {
	pub fn get(&self, index: u16) -> Option<MathValue<'a>> {
		self.get_(self.kern_values.get(index)?)
	}
	pub fn get_(&self, r: MathValueRecord) -> Option<MathValue<'a>> {
		Some(MathValue::new(r, self.data))
	}
}

#[derive(Debug, Clone)]
pub struct MathVariants<'a> {
	// UFWORD	minConnectorOverlap	Minimum overlap of connecting glyphs during glyph construction, in design units.
	pub min_connector_overlap: UFWORD,
	// Offset16	vertGlyphCoverageOffset	Offset to Coverage table, from the beginning of the MathVariants table.
	pub vert_glyph_coverage: Coverage<'a>,
	// Offset16	horizGlyphCoverageOffset	Offset to Coverage table, from the beginning of the MathVariants table.
	pub horiz_glyph_coverage: Coverage<'a>,
	// uint16	vertGlyphCount	Number of glyphs for which information is provided for vertically growing variants. Must be the same as the number of glyph IDs referenced in the vertical Coverage table.
	// uint16	horizGlyphCount	Number of glyphs for which information is provided for horizontally growing variants. Must be the same as the number of glyph IDs referenced in the horizontal Coverage table.
	// Offset16	vertGlyphConstructionOffsets[vertGlyphCount]	Array of offsets to MathGlyphConstruction tables, from the beginning of the MathVariants table, for shapes growing in the vertical direction.
	pub vert_glyph_construction: LazyOffsetArray16<'a, MathGlyphConstruction<'a>>,
	// Offset16	horizGlyphConstructionOffsets[horizGlyphCount]	Array of offsets to MathGlyphConstruction tables, from the beginning of the MathVariants table, for shapes growing in the horizontal direction.
	pub horiz_glyph_construction: LazyOffsetArray16<'a, MathGlyphConstruction<'a>>,
}
impl<'a> FromSlice<'a> for MathVariants<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		let min_connector_overlap = s.read()?;
		let vert_glyph_coverage = s.parse_at_offset16(data)?;
		let horiz_glyph_coverage = s.parse_at_offset16(data)?;
		let vert_glyph_count: u16 = s.read()?;
		let horiz_glyph_count: u16 = s.read()?;
		Some(Self {
			min_connector_overlap,
			vert_glyph_coverage,
			horiz_glyph_coverage,
			vert_glyph_construction: LazyOffsetArray16::new(data, s.read_array16(vert_glyph_count)?),
			horiz_glyph_construction: LazyOffsetArray16::new(data, s.read_array16(horiz_glyph_count)?),
		})
	}
}

#[derive(Debug, Clone, Copy)]
pub struct MathGlyphConstruction<'a> {
	// Offset16	glyphAssemblyOffset	Offset to the GlyphAssembly table for this shape, from the beginning of the MathGlyphConstruction table. May be NULL.
	pub glyph_assembly: GlyphAssembly<'a>,
	// uint16	variantCount	Count of glyph growing variants for this glyph.
	// MathGlyphVariantRecord	mathGlyphVariantRecords[variantCount]	MathGlyphVariantRecords for alternative variants of the glyphs.
	pub math_glyph_variant_records: LazyArray16<'a, MathGlyphVariantRecord>,
}
impl<'a> FromSlice<'a> for MathGlyphConstruction<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			glyph_assembly: s.parse_at_offset16(data)?,
			math_glyph_variant_records: s.parse_array16()?,
		})
	}
}

#[derive(Debug, Clone, Copy)]
pub struct GlyphAssembly<'a> {
	// MathValueRecord	italicsCorrection	Italics correction of this GlyphAssembly. Should not depend on the assembly size.
	pub italics_correction: MathValue<'a>,
	// uint16	partCount	Number of parts in this assembly.
	// GlyphPart	partRecords[partCount]	Array of GlyphPart records, from left to right (for assemblies that extend horizontally) or bottom to top (for assemblies that extend vertically).
	pub part_records: LazyArray16<'a, GlyphPart>,
}
impl<'a> FromSlice<'a> for GlyphAssembly<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			italics_correction: MathValue::new(s.read()?, data),
			part_records: s.parse_array16()?,
		})
	}
}

#[derive(Debug, Clone, Copy)]
pub struct GlyphPart {
	// uint16	glyphID	Glyph ID for the part.
	pub glyph_id: GlyphId,
	// UFWORD	startConnectorLength	Advance width/ height, in design units, of the straight bar connector material at the start of the glyph in the direction of the extension (the left end for horizontal extension, the bottom end for vertical extension).
	pub start_connector_length: UFWORD,
	// UFWORD	endConnectorLength	Advance width/ height, in design units, of the straight bar connector material at the end of the glyph in the direction of the extension (the right end for horizontal extension, the top end for vertical extension).
	pub end_connector_length: UFWORD,
	// UFWORD	fullAdvance	Full advance width/height for this part in the direction of the extension, in design units.
	pub full_advance: UFWORD,
	// uint16	partFlags	Part qualifiers. PartFlags enumeration currently uses only one bit:0x0001 EXTENDER_FLAG: If set, the part can be skipped or repeated.0xFFFE Reserved.
	pub part_flags: u16,
}
impl FromData for GlyphPart {
	const SIZE: usize = 10;
	fn parse(data: &[u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			glyph_id: s.read()?,
			start_connector_length: s.read()?,
			end_connector_length: s.read()?,
			full_advance: s.read()?,
			part_flags: s.read()?,
		})
	}
}

#[derive(Debug, Clone, Copy)]
pub struct MathGlyphVariantRecord {
	// uint16	variantGlyph	Glyph ID for the variant.
	pub variant_glyph: GlyphId,
	// UFWORD	advanceMeasurement	Advance width/height, in design units, of the variant, in the direction of requested glyph extension.
	pub advance_measurement: UFWORD,
}
impl FromData for MathGlyphVariantRecord {
	const SIZE: usize = 4;
	fn parse(data: &[u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			variant_glyph: s.read()?,
			advance_measurement: s.read()?,
		})
	}
}
